package three_shang.智能算法.AlgorithmCompare;

/**
 * @program: PSO
 * @description:
 * @author: DongGuoFeiFei
 * @create: 2024-10-22
 **/


import java.util.Random;

public class BatAlgorithm {
    // 蝙蝠算法参数
    private static final int N = 30; // 种群规模
    private static final int DIM = 8; // 维度
    private static final int GMAX = 10000; // 最大迭代次数
    private static final double FMIN = 0; // 最小频率
    private static final double FMAX = 2; // 最大频率
    private static final double ALPHA = 0.9; // 响度递减因子
    private static final double GAMMA = 0.9; // 脉冲递增因子
    private static final double VMAX = 5; // 最大速度
    private static final double VMIN = -5; // 最小速度
    private static final double XMAX = 10; // 最大位置
    private static final double XMIN = -10; // 最小位置
    private static final double INITIAL_A = 0.5; // 初始响度
    private static final double INITIAL_R = 0.5; // 初始脉冲发射率

    // 适应度函数
    private static double fitness(double[] x) {
        double denominator = Math.abs(x[0] + 1) + Math.abs(x[1]) + Math.abs(x[2] - 1) + Math.abs(x[3] - 2)
                + Math.abs(x[4] + 2) + Math.abs(x[5] - 3) + Math.abs(x[6] + 3) + 1;
        return 1.0 / denominator;
    }

    public static void main(String[] args) {
        Random random = new Random();

        // 初始化蝙蝠位置、速度、频率、响度和脉冲发射率
        double[][] position = new double[N][DIM];
        double[][] velocity = new double[N][DIM];
        double[] frequency = new double[N];
        double[] loudness = new double[N];
        double[] pulseRate = new double[N];
        double[][] bestPosition = new double[N][DIM];
        double[] fitnessValue = new double[N];
        double[] gBest = new double[DIM];
        double gBestFitness = Double.MIN_VALUE;

        // 初始化种群
        for (int i = 0; i < N; i++) {
            loudness[i] = INITIAL_A;
            pulseRate[i] = INITIAL_R;
            for (int j = 0; j < DIM; j++) {
                position[i][j] = XMIN + (XMAX - XMIN) * random.nextDouble();
                velocity[i][j] = VMIN + (VMAX - VMIN) * random.nextDouble();
                bestPosition[i][j] = position[i][j];
            }
            fitnessValue[i] = fitness(position[i]);
            if (fitnessValue[i] > gBestFitness) {
                gBestFitness = fitnessValue[i];
                System.arraycopy(position[i], 0, gBest, 0, DIM);
            }
        }

        // 蝙蝠算法迭代过程
        for (int g = 0; g < GMAX; g++) {
            for (int i = 0; i < N; i++) {
                // 计算频率
                frequency[i] = FMIN + (FMAX - FMIN) * random.nextDouble();

                // 更新速度和位置
                for (int j = 0; j < DIM; j++) {
                    velocity[i][j] = velocity[i][j] + (position[i][j] - gBest[j]) * frequency[i];
                    // 限制速度
                    if (velocity[i][j] > VMAX) velocity[i][j] = VMAX;
                    if (velocity[i][j] < VMIN) velocity[i][j] = VMIN;

                    position[i][j] = position[i][j] + velocity[i][j];
                    // 限制位置
                    if (position[i][j] > XMAX) position[i][j] = XMAX;
                    if (position[i][j] < XMIN) position[i][j] = XMIN;
                }

                // 以一定概率执行局部搜索
                if (random.nextDouble() > pulseRate[i]) {
                    for (int j = 0; j < DIM; j++) {
                        position[i][j] = gBest[j] + (random.nextDouble() - 0.5) * loudness[i];
                    }
                }

                // 计算新位置的适应度值
                double newFitness = fitness(position[i]);

                // 接受新的解并更新全局最优解
                if (newFitness > fitnessValue[i] && random.nextDouble() < loudness[i]) {
                    System.arraycopy(position[i], 0, bestPosition[i], 0, DIM);
                    fitnessValue[i] = newFitness;

                    // 更新响度和脉冲发射率
                    loudness[i] *= ALPHA;
                    pulseRate[i] = INITIAL_R * (1 - Math.exp(-GAMMA * g));

                    // 更新全局最优解
                    if (newFitness > gBestFitness) {
                        gBestFitness = newFitness;
                        System.arraycopy(position[i], 0, gBest, 0, DIM);
                    }
                }
            }

            // 打印迭代信息
            if (g % 500 == 0) {
                System.out.println("次数: " + g + "最佳适应值: " + gBestFitness);
            }
        }
        System.out.println("次数: 10000" + "最佳适应值: " + gBestFitness);

        // 输出最终结果
        System.out.println("Best solution: ");
        for (int j = 0; j < DIM; j++) {
            System.out.print(gBest[j] + "、");
        }
    }
}

